#include <stdio.h>
// #include "board.h"
#include "dap_usb_handle.h"
#include "driver/uart.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "usb_log.h"
#include "usb2uart.h"
static const char *TAG = "usb2uart";
// 定义连续相同字符的数量，用于 UART 模式检测
#define PATTERN_CHR_NUM (3)
// 定义使用的 UART 编号为 1
#define EX_UART_NUM UART_NUM_1
// 定义缓冲区大小为 1024 字节
#define BUF_SIZE (1024)
// 定义读取缓冲区大小为 1024 字节
#define RD_BUF_SIZE (BUF_SIZE)
// 定义日志标签

/*      每个 UART 事件队列的大小        */
#define UART_QUEUE_SIZE (20)
/*      UART队列集                      */
static QueueSetHandle_t uart_all_queueSet;
// 定义 UART 事件队列句柄
static QueueHandle_t uart0_queue;
static QueueHandle_t uart1_queue;
static QueueHandle_t uart2_queue;

// 定义 UART 任务句柄指针
static TaskHandle_t *uart_task_handle = NULL;

int uart_queue2queueSet(QueueSetHandle_t queueSet)
{
    /*添加到队列集中*/
    return xQueueAddToSet(queueSet, uart_all_queueSet);
}

/**
 * @brief UART 事件处理任务
 * 
 * 该任务负责处理 UART 事件，如接收到数据、FIFO 溢出、缓冲区满等。
 * 
 * @param pvParameters 任务参数，此处未使用
 */
static void uart_event_task(void *pvParameters)
{
    // 打印日志，表明 UART 事件任务开始
    //ESP_LOGI(TAG, "uart_event_task start", EX_UART_NUM);
    // 定义 UART 事件结构体
    uart_event_t event;
    // 定义缓冲区大小变量
    size_t buffered_size;
    //
    QueueHandle_t uart_queue_tmp;
    uart_num_t uart_num_tmp = UART_MAX_NUM;

    // 分配读取缓冲区内存
    uint8_t *dtmp = (uint8_t *)malloc(RD_BUF_SIZE);
    // 检查内存分配是否成功
    if (!dtmp) {
        // 内存分配失败，打印错误日志并删除任务
        ESP_LOGE(TAG, "Failed to allocate buffer");
        vTaskDelete(NULL);
        return;
    }
    // 无限循环处理 UART 事件
    for (;;) {
        // 任务延迟 1 个 tick
        // 从 UART 事件队列中接收事件，超时时间为 1 个 tick
        uart_queue_tmp = xQueueSelectFromSet(uart_all_queueSet, portMAX_DELAY);
        //xQueueReceive(uart1_queue ,&event,portMAX_DELAY);
        //ESP_LOGI(TAG, "uart1_queue receive %x", uart_queue_tmp);
        if (xQueueReceive(uart_queue_tmp, (void *)&event, (TickType_t)1)) {
            if (uart_queue_tmp == uart0_queue) {
                uart_num_tmp = UART_SHELL_NUM;
            } else if (uart_queue_tmp == uart1_queue) {
                uart_num_tmp = UART_ACM_NUM;
            } else if (uart_queue_tmp == uart2_queue) {
                uart_num_tmp = UART_SWO_NUM;
            }

            // 清空读取缓冲区
            //bzero(dtmp, RD_BUF_SIZE);
            // 打印 UART 事件信息（可选，已注释）
            // ESP_LOGI(TAG, "uart[%d] event: %d", EX_UART_NUM, event.type);
            // 根据事件类型进行处理
            switch (event.type) {
                // 接收到 UART 数据事件
                case UART_DATA:
                    /*        uart0->shell,uart1->usb2uart,uart2->SWO             */
                    if (uart_num_tmp == UART_ACM_NUM) {
                        // 获取 UART 接收缓冲区中的数据长度
                        uart_get_buffered_data_len(UART_NUM_1, &buffered_size);
                        // 如果缓冲区中有数据
                        if (buffered_size > 0) {
                            // 清空读取缓冲区
                            //bzero(dtmp, RD_BUF_SIZE);
                            // 从 UART 读取数据到缓冲区
                            uart_read_bytes(EX_UART_NUM, dtmp, buffered_size, pdMS_TO_TICKS(20));
                            //!没有做防止覆盖操作，该任务是所有uart的，不应该阻塞在这里
                            //ESP_EARLY_LOGI(TAG, "uart1->usb2uart, data len: %d", buffered_size);
                            xRingbufferSend(g_dap_usb_config.uart2usb_RB_handle, dtmp, buffered_size, pdMS_TO_TICKS(20));
                            xEventGroupSetBits(g_dap_usb_config.usb_uart_event, USB_UART_UART2USB_EVENT);
                            //ESP_EARLY_LOGI(TAG, "USB_UART_UART2USB_EVENT ok");
                        }
                    } else {
                        //
                    }

                    break;
                // UART FIFO 溢出事件
                case UART_FIFO_OVF:
                    // 打印 FIFO 溢出日志
                    ESP_LOGI(TAG, "hw fifo overflow");
                    // 清空 UART 输入缓冲区
                    uart_flush_input(EX_UART_NUM);
                    // 重置 UART 事件队列
                    xQueueReset(uart1_queue);
                    break;
                // UART 环形缓冲区满事件
                case UART_BUFFER_FULL:
                    // 打印环形缓冲区满日志
                    ESP_LOGI(TAG, "ring buffer full");
                    // 清空 UART 输入缓冲区
                    uart_flush_input(EX_UART_NUM);
                    // 重置 UART 事件队列
                    xQueueReset(uart1_queue);
                    break;
                // UART RX 中断事件
                case UART_BREAK:
                    // 配置 UART 线路编码（可选，已注释）
                    // struct cdc_line_coding line_coding = {
                    //     dwDTERate: 115200,
                    //     bCharFormat: 0,
                    //     bParityType: UART_PARITY_DISABLE,
                    //     bDataBits: 8
                    // };
                    // chry_dap_usb2uart_uart_config_callback(&line_coding);
                    // 打印 RX 中断日志
                    //ESP_LOGI(TAG, "uart rx break");
                    break;
                // UART 奇偶校验错误事件
                case UART_PARITY_ERR:
                    // 打印奇偶校验错误日志
                    ESP_LOGI(TAG, "uart parity error");
                    break;
                // UART 帧错误事件
                case UART_FRAME_ERR:
                    // 打印帧错误日志
                    ESP_LOGI(TAG, "uart frame error");
                    break;
                // UART 模式检测事件
                case UART_PATTERN_DET:
                    // 获取 UART 接收缓冲区中的数据长度
                    uart_get_buffered_data_len(EX_UART_NUM, &buffered_size);
                    // 获取模式检测位置
                    int pos = uart_pattern_pop_pos(EX_UART_NUM);
                    // 打印模式检测信息
                    ESP_LOGI(TAG, "[UART PATTERN DETECTED] pos: %d, buffered size: %d", pos, buffered_size);
                    // 如果模式位置队列为空
                    if (pos == -1) {
                        // 清空 UART 输入缓冲区
                        uart_flush_input(EX_UART_NUM);
                    } else {
                        // 从 UART 读取数据到缓冲区
                        uart_read_bytes(EX_UART_NUM, dtmp, pos, 100 / portTICK_PERIOD_MS);
                        // 定义模式字符数组
                        uint8_t pat[PATTERN_CHR_NUM + 1];
                        // 清空模式字符数组
                        memset(pat, 0, sizeof(pat));
                        // 从 UART 读取模式字符到数组
                        uart_read_bytes(EX_UART_NUM, pat, PATTERN_CHR_NUM, 100 / portTICK_PERIOD_MS);
                        // 打印读取的数据信息
                        ESP_LOGI(TAG, "read data: %s", dtmp);
                        // 打印读取的模式字符信息
                        ESP_LOGI(TAG, "read pat : %s", pat);
                    }
                    break;
                // 其他事件
                default:
                    // 打印未知事件类型日志
                    ESP_LOGI(TAG, "uart event type: %d", event.type);
                    break;
            }
        }
    }
    // 打印 UART 事件任务停止日志
    ESP_LOGI(TAG, "uart_event_task stop", EX_UART_NUM);
    // 释放读取缓冲区内存
    free(dtmp);
    dtmp = NULL;
    // 删除当前任务
    vTaskDelete(NULL);
}

/**
 * @brief UART 预初始化函数
 * 
 * 该函数用于初始化 UART 配置并创建 UART 事件处理任务。
 */
void uartx_preinit(void)
{
    // 定义 UART 线路编码结构体并初始化
    struct cdc_line_coding line_coding = {
        dwDTERate: 115200,
        bCharFormat: 0,
        bParityType: UART_PARITY_DISABLE,
        bDataBits: 8
    };
    // 调用 UART 配置回调函数
    dap_usb2uart_uart_config_callback(&line_coding);

    uart_all_queueSet = xQueueCreateSet(3 * UART_QUEUE_SIZE);
    uart_queue2queueSet(uart1_queue);
    //ESP_LOGI(TAG, "uart_queue2queueSet ret %d", ret);
    // 创建 UART 事件处理任务
    xTaskCreatePinnedToCore(uart_event_task, "uart_event_task", 3072, NULL, 10, uart_task_handle, 1);
}

/**
 * @brief UART 配置回调函数
 * 
 * 该函数用于根据传入的线路编码结构体配置 UART 参数，并安装 UART 驱动。
 * 
 * @param line_coding 线路编码结构体指针
 */
void dap_usb2uart_uart_config_callback(struct cdc_line_coding *line_coding)
{
    // 定义 UART 配置结构体
    uart_config_t uart_config;

    // 禁用备份功能
    // uart_config.flags.allow_pd = 0;
    uart_config.flags.backup_before_sleep = 0;

    // 设置波特率
    uart_config.baud_rate = line_coding->dwDTERate;
    // 设置数据位
    uart_config.data_bits = line_coding->bDataBits ? line_coding->bDataBits - 5 : UART_DATA_8_BITS;
    // 设置停止位
    uart_config.stop_bits = line_coding->bDataBits ? line_coding->bCharFormat + 1 : UART_STOP_BITS_1;
    // 禁用奇偶校验
    // uart_config.parity = line_coding->bParityType;
    uart_config.parity = UART_PARITY_DISABLE;
    // 禁用硬件流控制
    uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE;
    // 设置时钟源为 APB
    uart_config.source_clk = UART_SCLK_APB;
    // 设置时钟源（可选，已注释）
    // uart_config.source_clk = UART_SCLK_DEFAULT;
    // 设置接收流控制阈值
    uart_config.rx_flow_ctrl_thresh = 122;

    // 打印 UART 配置信息
    //USB_LOG_INFO("config uart, data bit %d bDataBits %d\r\n", uart_config.data_bits, line_coding->bDataBits);
    // 配置 UART 参数
    uart_param_config(UART_NUM_1, &uart_config);
    // 设置 UART 引脚
    uart_set_pin(UART_NUM_1, DAP_UART_TX, DAP_UART_RX, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
    // 如果 UART 驱动未安装，则安装驱动
    if (!uart_is_driver_installed(UART_NUM_1))
        uart_driver_install(UART_NUM_1, CONFIG_UARTRX_RINGBUF_SIZE, CONFIG_USBRX_RINGBUF_SIZE, UART_QUEUE_SIZE, &uart1_queue, 0);
}
